Code of the statistical analysis for the article ‘Life Beyond A Jar: Effects of Tank Size and Enrichment on the Behaviour and Welfare of Siamese Fighting Fishes’
Author
Juliette Tariel-Adam
Published
April 15, 2024
The script contains the code of data transformation, analysis and graphs for the article “Life Beyond A Jar: Effects of Tank Size and Enrichment on the Behaviour and Welfare of Siamese Fighting Fishes” by XXauthorsXXX. It is in two versions: the raw R script in qmd format and the code output in html format.
The goal was to test the effect of tank enrichment and size on Siamese fish behaviour. The tanks Jar, Small, Medium and Large are compared among each other, and the tank Large and Barren between each other. Barren is not compared to Jar, Small or Medium because they differ by two factors: enrichment and size.
On the html version of the code, you fill find below a first row of tabs to click on (PCA, Swimming, etc) and for most of these tabs, a second row of tabs to click on (Distribution, Plot, etc).
After staying 3-7 days in a tank, the behaviour of all fish were scored by four 10-min trials in their tank. All trials occurred on the same day at 4 different times (7 am, 10 am, 2 pm, 6 pm). During the 10 min trial = 600 sec, the fish’s behaviour was assigned to one of the 10 behaviours, meaning that the behaviours are mutually exclusive (for instance, a fish can’t be scored as nest building and interacting with the surface at the same time): Resting, Swimming, Hovering, Sinking/Floating, Stereotypic swimming, Nest building, Foraging, Interation with surface, Out of view, Unsure. Unsure is not present in the raw dataset. Out.of.view is a bit special because it is not a behaviour and was not analysed. Sinking/Floating was not analysed (see explanation in the PCA section).
The data has been inspected and corrected for data entry errors (sum of scored behaviours too low/high, column shifted, typos, inconsistent nb of observations per fish/time/tank…).
Each row represents a trial. For each trial, there is: + Fish: the fish tested + Tank: in which tank the fish was + Order: the tank order, i.e. whether it was the first, second, …, fifth tank that the fish experienced. + Time: time of the day at which the trial happened + Filter: where there a filter in the tank + Behavioural columns. The columns for the behaviours are the time spent doing the specific behaviour in seconds during the trial. Some behaviours (Forgaging, Hovering, Interaction.with.Surface, Stereotypic.swimming) have been trasnformed in binary variable (.bin). The columns .bins represents if the fish performed the specific behaviour at all during the trial or not.
summary(data)
Fish Tank Order Time Filter
Elf : 20 Jar :48 Min. :1.000 7:00 AM :63 No-filter:180
Fairy : 20 Small :52 1st Qu.:2.000 10:00 AM:63 Filter : 72
Ghost : 20 Medium:52 Median :3.000 2:00 PM :63
Goblin : 20 Large :52 Mean :2.968 6:00 PM :63
Kinara : 20 Barren:48 3rd Qu.:4.000
Kraken : 20 Max. :5.000
(Other):132
Swimming Resting Hovering Stereotypic.swimming
Min. : 0.0 Min. : 0.00 Min. : 0.00 Min. : 0.00
1st Qu.:133.9 1st Qu.: 92.33 1st Qu.: 6.01 1st Qu.: 0.00
Median :224.8 Median :190.99 Median : 23.71 Median : 0.00
Mean :224.6 Mean :226.04 Mean : 42.93 Mean : 42.47
3rd Qu.:309.2 3rd Qu.:354.97 3rd Qu.: 56.21 3rd Qu.: 20.58
Max. :486.8 Max. :600.00 Max. :344.27 Max. :549.00
Nest.building Foraging Interation.with.surface Foraging.bin
Min. : 0.00 Min. : 0.00 Min. : 0.000 No :168
1st Qu.: 0.00 1st Qu.: 0.00 1st Qu.: 0.000 Yes: 84
Median : 0.00 Median : 0.00 Median : 1.545
Mean : 33.72 Mean : 7.83 Mean : 15.331
3rd Qu.: 0.00 3rd Qu.: 7.80 3rd Qu.: 14.117
Max. :512.99 Max. :125.28 Max. :251.000
SS.bin Hovering.bin Interacting.bin Nest.bin
No :172 No : 48 No :125 No :201
Yes: 80 Yes:204 Yes:127 Yes: 51
# Number of observations per fish per tankdata %>%group_by(Fish, Tank) %>%summarise(n=n(), .groups ='drop') %>%spread(Tank,n)
plot1("Filter", main = data3, beh_cols = beh.cols3, palette = palette.beh3)
There have never been a filter in Jar or Small. Some fish never had a filter in their tank. Filter needs to be included in all models as a control variable.
We run a PCA in order to:
Try to reduce the number of variables to analyse
Determine which behaviours were important to explain the variability between trials
See correlations between behaviours
The PCA did not help reduce the number of variables to analyse (see Analysis_PCA.html for more explanation) so the behaviours were analysed separately with linear models. The advantage of separate linear models compared to the PCA is the possibility to quantitatively interpret the differences between tanks.
Even if we did not use PCA for further analysis, the first 4 components are plotted below, which explained 71% of variance in the data, to show the important variables and the correlations between variables.
The 1st PCA component was driven by Resting (cos2 = 0.8), Swimming (0.7) and Foraging (0.3). Swimming and Foraging opposite to Resting. This first component could be interpret as “activity”. If a fish spent a lot of time swimming and foraging during a trial, it was very little resting. This first component explained 25% of the variance in the data (as a reminder, the data is the time spent performing the different types of behaviour). So 1 quarter of the variance is a matter of activity. Keep in mind for the rest of the analyses that these behavioural types are correlated.
The 2nd PCA component was driven by Hovering (cos2 = 0.5) and Stereotypic.swimming (0.5), and a bit by Interaction with surface (0.16). Hovering and Interacting.with.Surface opposite to Stereotypic.swimming. If the fish spent a lot of time hovering (and interacting with the surface), it was very little stereotypic swimming.
The 3rd PCA component was driven mainly by Nest building (cos2 = 0.6), and a bit by Foraging (0.16), Resting (0.14) and Stereotypic Swimming (0.13). Foraging and Resting opposite to Nest building and Stereotypic Swimming. If a fish spent time foraging and resting in a trial, it was little nest building and stereotypic swimming. This makes sense, it a fish is building a nest,it is an important task and needs to be finished, so it is not scattering its time with other activities. The apparent correlation between nest building and stereotypic swimming could be due to Jar where fish in this tank rarely engaged in nest building or stereotypic swimming.
The 4th PCA component was not easily interpretable = not easily linked to the initial behavioural variables.
Sinking/Floating contributed almost nothing to the PCA (1.8%) + did not correlate strongly with any of the component. Sinking/Floating was not important to explain the variability between trials. We did not further analyse this behaviour.
The first plot is to see the trend by tank. Big red dots is for the overall mean by tank. Small black points are raw data = swimming time of each trial.
The second plot is to see the trend by fish and by tank. The dashed black line is means by tank. The other lines are the means for each fish by tank.
plot_var(data, "Swimming")
plot_var_fish(data, "Swimming")
mSwimming <-lmer(Swimming ~ Tank + Time + Filter + (1|Fish), data = data)anova(mSwimming, ddf ="Kenward-Roger", type =2)
Type II Analysis of Variance Table with Kenward-Roger's method
Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
Tank 240332 60083 4 236.97 10.065 1.535e-07 ***
Time 337219 112406 3 231.05 18.832 5.812e-11 ***
Filter 111221 111221 1 151.81 18.633 2.846e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
emmeans(mSwimming, ~ Time) # estimated means of time spent swimming depending on the time of the day
Time emmean SE df lower.CL upper.CL
7:00 AM 301 14.9 28.9 270 331
10:00 AM 243 14.9 28.9 212 273
2:00 PM 206 14.9 28.9 176 237
6:00 PM 216 14.9 28.9 186 247
Results are averaged over the levels of: Tank, Filter
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
emmeans(mSwimming, ~ Filter)
Filter emmean SE df lower.CL upper.CL
No-filter 202 12.8 15.2 175 229
Filter 281 17.6 34.4 246 317
Results are averaged over the levels of: Tank, Time
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Effect of Tank, Time and Filter!
Tank. Large swam significantly more time than Jar, Small and Medium. Fish in Large swan 93 sec [CI 45, 140] more than Jar (over a 600 sec trial), 79 sec [CI 32, 126] more than Small, and 81 sec [CI 39, 122] more than Medium. In addition, fish in Large swam significantly more time (58 sec [CI 16, 101]) than fish in Barren.
Time. Fish swim more in the morning than in the afternoon, especially at 7 am.
Filter. Fish swim more with a filter in their tank.
# Uncomment the 2 lines below if running the script for the first time## rpt.swimming <- rpt(Swimming ~ Tank + Time + Filter + (1|Fish), grname = "Fish", data = data, datatype = "Gaussian", nboot = 1000, npermut = 1000)## save(rpt.swimming, file = "Script/Repeatability rptR output/rpt.swimming")base::load("Script/Repeatability rptR output/rpt.swimming")summary(rpt.swimming)
Repeatability estimation using the lmm method
Call = rpt(formula = Swimming ~ Tank + Time + Filter + (1 | Fish), grname = "Fish", data = data, datatype = "Gaussian", nboot = 1000, npermut = 1000)
Data: 252 observations
----------------------------------------
Fish (13 groups)
Repeatability estimation overview:
R SE 2.5% 97.5% P_permut LRT_P
0.198 0.0802 0.0441 0.352 0.001 0
Bootstrapping and Permutation test:
N Mean Median 2.5% 97.5%
boot 1000 0.19068 0.186 0.0441 0.3520
permut 1000 0.00981 0.000 0.0000 0.0504
Likelihood ratio test:
logLik full model = -1459.844
logLik red. model = -1474.76
D = 29.8, df = 1, P = 2.35e-08
----------------------------------------
Likelihood ratio test indicates a statistically significant random effect. Meaning that fish behaved differently among each others in terms of swimming. But the repeatability is quite low (0.2 [95% CI 0.04, 0.35]).
Time emmean SE df lower.CL upper.CL
7:00 AM 141 29.1 19.6 80.1 202
10:00 AM 199 29.1 19.6 137.8 259
2:00 PM 259 29.1 19.6 198.1 320
6:00 PM 286 29.1 19.6 225.7 347
Results are averaged over the levels of: Tank, Filter
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Effect of Tank and Time.
Tank. Large rested significantly less time than Jar and Medium (almost significant for Small). Fish in Large rested 110 sec [CI 39, 181] more than fish in Jar (over a 600 sec trial), and 114 sec [CI 53, 175] more fish in Medium. This is in line with the PCA and the results of Swimming: Fish that spent time swimming spent less time resting. Fish in Large were overall more active. No significant difference between Large and Barren.
Time. Fish rest less time in the morning, especially at 7 am. In line with the PCA and the results of Swimming.
# Uncomment the 2 lines below if running the script for the first time## rpt.resting <- rpt(Resting ~ Tank + Time + Filter + (1|Fish), grname = "Fish", data = data, datatype = "Gaussian", nboot = 1000, npermut = 1000)## save(rpt.resting, file = "Script/Repeatability rptR output/rpt.resting")base::load("Script/Repeatability rptR output/rpt.resting")summary(rpt.resting)
Repeatability estimation using the lmm method
Call = rpt(formula = Resting ~ Tank + Time + Filter + (1 | Fish), grname = "Fish", data = data, datatype = "Gaussian", nboot = 1000, npermut = 1000)
Data: 252 observations
----------------------------------------
Fish (13 groups)
Repeatability estimation overview:
R SE 2.5% 97.5% P_permut LRT_P
0.369 0.106 0.153 0.562 0.001 0
Bootstrapping and Permutation test:
N Mean Median 2.5% 97.5%
boot 1000 0.36078 0.359 0.153 0.5617
permut 1000 0.00933 0.000 0.000 0.0452
Likelihood ratio test:
logLik full model = -1565.567
logLik red. model = -1599.854
D = 68.6, df = 1, P = 6.1e-17
----------------------------------------
Likelihood ratio test indicates a statistically significant random effect. Meaning that fish behaved differently among each others in terms of swimming. The repeatability is OK 0.37 [95% CI 0.15, 0.56].
lm_diagnosis(mResting)
[1] "check constant variance over fitted values"
[1] "Normality of Resting"
[1] "Normality random residuals"
The model seems good.
Just a plot with the amount of time resting at the different places depending on the tank. Each bar value is the mean of resting times over trials and fish.
From the graphs, we can see that fish use different places to rest, not only one type. They use all the different places available. It does not seem that there is a preferred resting place.
hist1(data$Hovering[data$Hovering!=0]) # histogram without the zeros
Even if there are less zeros than Foraging or Stereotypic Swimming, it is not a normal distribution. There were only 48 trials (out of 252) during which no hovering happened. So 204 trials where we could study the amount of time hovering in 204 trials.
We fitted a glm distribution like Foraging and Stereotypic Swimming on the probability to hover (dependent variable is 1 if hovering occurred during the trial, zero otherwise).
To analyse the amount of time the fish was hovering on the 204 trials with hovering time > 0, we tried different models described in “Analysis_Hovering”. The best model was a linear mixed model on the amount of time spent hovering with weighted least squares.
# Effect of tank of the probability to hover during a trialplot_var_binary(data, "Hovering.bin")
plot_var_binary_fish(data, "Hovering.bin")
# Among the trials where the fish hovers, effect of tank on the amount of time hoveringdata %>%filter(Hovering >0) %>%plot_var(., "Hovering")
data %>%filter(Hovering >0) %>%plot_var_fish(., "Hovering")
Both the probability to hover and the time spent hovering seems to be higher in Jar compared to the others. All fish besides Goblin hovered more in Jar compared to Small.
Y variable = probability to hover during a trial
mHovering <-glmmTMB(Hovering.bin ~ Tank + Time + Filter + (1|Fish), data = data, family =binomial)glmmTMB:::Anova.glmmTMB(mHovering)
Time prob SE df asymp.LCL asymp.UCL
7:00 AM 0.917 0.0398 Inf 0.798 0.969
10:00 AM 0.870 0.0525 Inf 0.729 0.943
2:00 PM 0.728 0.0786 Inf 0.551 0.854
6:00 PM 0.747 0.0760 Inf 0.573 0.866
Results are averaged over the levels of: Tank, Filter
Confidence level used: 0.95
Intervals are back-transformed from the logit scale
emmeans(mHovering, ~ Filter, type ="response")
Filter prob SE df asymp.LCL asymp.UCL
No-filter 0.900 0.0343 Inf 0.810 0.950
Filter 0.729 0.0933 Inf 0.516 0.872
Results are averaged over the levels of: Tank, Time
Confidence level used: 0.95
Intervals are back-transformed from the logit scale
No effect of Tank on the probability to hover during a trial, only an effect of Time and filter
Time. Fish were less likely to hover in the afternoon.
Filter. Fish were less likely to hover with a filter in their tank.
Y variable = amount of time spent hovering during a trial. Only trials with hovering time > 0
Linear model with weighted least squares
mHovering2 <-lme(Hovering ~ Tank + Time + Filter, random =~1| Fish, data = data[data$Hovering>0,], weights =varPower(), control =lmeControl(maxIter =20000))anova(mHovering2)
emmeans(mHovering2, ~ Time) # estimated means of time spent Hovering depending on the time of the day
Time emmean SE df lower.CL upper.CL
7:00 AM 39.3 5.06 12 28.2 50.3
10:00 AM 48.3 5.72 12 35.8 60.8
2:00 PM 48.1 5.68 12 35.7 60.4
6:00 PM 42.4 5.23 12 31.0 53.8
Results are averaged over the levels of: Tank, Filter
Degrees-of-freedom method: containment
Confidence level used: 0.95
emmeans(mHovering2, ~ Filter)
Filter emmean SE df lower.CL upper.CL
No-filter 52.2 5.30 12 40.7 63.8
Filter 36.8 6.53 12 22.5 51.0
Results are averaged over the levels of: Tank, Time
Degrees-of-freedom method: containment
Confidence level used: 0.95
Effect of Tank, Time and Filter.
Tank. Jar hovered significantly more time than Small, Medium and Large. Fish in Jar hovered 53 sec [CI 20, 85] more than Small (over a 600 sec trial), 53 sec [CI 20, 86] more than Medium, and 61 sec [CI 28, 93] more than Large. Fish in medium hovered more time than fish in Large. In addition, fish in Barren hovered significantly more time (22 sec [CI 9, 35]) than fish in Large.
Time. Fish hovered more time in the middle of the day.
Filter. Fish hovered less time with a filter in their tank.
The data are clearly not following a normal distribution. It seems that a beta distribution could suit but foraging is not a continuous variable ranging from 0 to 1. Foraging has thus been analysed as a binary variable: 1 if fish spent time foraging during this trial, 0 otherwise.
There were 168 trials (out of 252) during which no foraging happened.
The plots are in percentage of trials during which the fish foraged over the total number of trials.
plot_var_binary(data, "Foraging.bin")
plot_var_binary_fish(data, "Foraging.bin")
mForaging <-glmmTMB(Foraging.bin ~ Tank + Time + Filter + (1|Fish), data = data, family =binomial)glmmTMB:::Anova.glmmTMB(mForaging)
# example of differences between Jar and Large## Contrast estimate1/0.08
[1] 12.5
## Lower CI1/0.437
[1] 2.28833
## Upper CI1/0.014
[1] 71.42857
Effect of Tank.
As a reminder, an odds.ratio < 1 between tank X vs tank Y means the probability of foraging during a trial in tank X is smaller that the probability of foraging during a trial in tank Y. An odd ratio for instance of 0.2 means that a fish is (1 / 0.2) = five times more likely to forage during a trial in tank Y than in Tank X. If we imagine 5 trials, fish will forage on average during 1 trial out of 5 in Tank X whereas fish will forage on average during 5 trials out of 5 in Tank Y.
Tank. Fish were more likely to forage during a trial in Large compared to Jar, Small and Medium. Again in accordance with the PCA and the results of Swimming and Resting. Fish in Large were on average 13 times [CI 2, 71] more likely to forage during a trial than fish in Jar, 25 times [CI 4, 166] than fish in Small, and 4 times [CI 1, 13] than fish in Medium. In addition, fish were 15 times [CI 3, 63] more likely to forage during a trial in Large than Barren. In accordance with the PCA and the results of Swimming. This time, there was also a significant difference between small and medium.
# Attempt to calculate repeatabilityrpt.foraging <-rpt(Foraging.bin ~ Tank + Time + Filter + (1|Fish), grname ="Fish", data = data, datatype ="Binary", nboot =0, npermut =0)
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.00341065 (tol = 0.002, component 1)
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.00341065 (tol = 0.002, component 1)
# attempt with package glmer rather than glmmTMBmForaging2 <-glmer(Foraging.bin ~ Tank + Time + Filter + (1|Fish), data = data, family ="binomial")
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.00341065 (tol = 0.002, component 1)
# Likelihood ratio test of random effectmForaging0 <-glm(Foraging.bin ~ Tank + Time + Filter, data = data, family =binomial)lrtest(mForaging0, mForaging)
Warning in modelUpdate(objects[[i - 1]], objects[[i]]): original model was of
class "glm", updated model is of class "glmmTMB"
Likelihood ratio test
Model 1: Foraging.bin ~ Tank + Time + Filter
Model 2: Foraging.bin ~ Tank + Time + Filter + (1 | Fish)
#Df LogLik Df Chisq Pr(>Chisq)
1 9 -139.71
2 10 -130.34 1 18.734 1.503e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Error when calculating the repeatability with rptR. Hard to estimate repeatability on binary data. I don’t know how to do it without the package rptR. I think we don’t have enough data power anyway to calculate repeatability with a binary variable. I tried to use the lmer package to calculate the repeatability with rptR but the model failed to converge when using glmer()
Likelihood ratio test indicates a statistically significant random effect. Meaning that fish behaved differently among each others in terms of foraging.
Tank. Jar were less likely to perform stereotypic swimming during a trial than Small/Medium/Large but only significant between Jar and Small. Fish in Small were 33 times [CI 4, 333] more likely to perform stereotypic swimming during a trial than fish in Jar.
# Attempt to calculate repeatabilityrpt.SS <-rpt(SS.bin ~ Tank + Time + Filter + (1|Fish), grname ="Fish", data = data, datatype ="Binary", nboot =0, npermut =0)
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.00627069 (tol = 0.002, component 1)
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.00627069 (tol = 0.002, component 1)
# attempt with package glmer rather than glmmTMBmSS2 <-glmer(SS.bin ~ Tank + Time + Filter + (1|Fish), data = data, family ="binomial")
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.00627069 (tol = 0.002, component 1)
# Likelihood ratio test of random effectmSS0 <-glm(SS.bin ~ Tank + Time + Filter, data = data, family =binomial)lrtest(mSS0, mSS)
Warning in modelUpdate(objects[[i - 1]], objects[[i]]): original model was of
class "glm", updated model is of class "glmmTMB"
Likelihood ratio test
Model 1: SS.bin ~ Tank + Time + Filter
Model 2: SS.bin ~ Tank + Time + Filter + (1 | Fish)
#Df LogLik Df Chisq Pr(>Chisq)
1 9 -129.71
2 10 -92.88 1 73.661 < 2.2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Error when calculating the repeatability with rptR, idem Foraging.
Likelihood ratio test indicates a statistically significant random effect. Meaning that fish behaved differently among each others in terms of stereotypic swimming.
mSS_res <-simulateResiduals(mSS)plot(mSS_res)
plotResiduals(mSS_res, form = data$Tank)
plotResiduals(mSS_res, form = data$Time)
plotResiduals(mSS_res, form = data$Filter)
# Problem with Filter, I retried the model without FiltermSS2 <-glmmTMB(SS.bin ~ Tank + Time + (1|Fish), data = data, family =binomial)plot(simulateResiduals(mSS2))
It is expected to have a problem with filter as there are more than twice more trials without filter than with filter. No problem when removing Filter from the model. The model seems good.
Just a plot with the type of stereotypic swimming depending on the tank. To stick with the analysis, it is a count (count = 1 if the fish performs a certain type of stereotypic swimming during a trial).
It seems that there are not differences between tanks. Just circles seem specific to larger tanks (Medium/Large/Barren).
Tank Fish Time Stereotypic.swimming.type Nb.rep
1 Small Dragon 7:00 AM Pacing 328
2 Small Dragon 10:00 AM Pacing 76
3 Small Dragon 2:00 PM Pacing 20
4 Small Dragon 6:00 PM Pacing 8
5 Small Dragon 6:00 PM Pacing front wall 8
6 Barren Dragon 7:00 AM Pacing 4
7 Barren Dragon 10:00 AM Pacing 5
8 Barren Dragon 2:00 PM Pacing 19
9 Barren Dragon 6:00 PM Pacing 4
10 Jar Elf 7:00 AM Zig zag 4
11 Jar Elf 6:00 PM Zig zag 6
12 Small Elf 7:00 AM Pacing 15
13 Small Elf 10:00 AM Pacing 15
14 Small Elf 2:00 PM Pacing 109
15 Small Elf 6:00 PM Pacing 25
16 Medium Elf 7:00 AM Pacing 4
17 Medium Elf 10:00 AM Pacing 34
18 Medium Elf 2:00 PM Pacing 14
19 Large Elf 10:00 AM Circles 12
20 Large Elf 10:00 AM Pacing 8
21 Barren Elf 7:00 AM Pacing 186
22 Barren Elf 10:00 AM Pacing 8
23 Barren Elf 6:00 PM Pacing 8
24 Small Fairy 7:00 AM Pacing 234
25 Small Fairy 10:00 AM Pacing 340
26 Small Fairy 2:00 PM Pacing 381
27 Small Fairy 6:00 PM Pacing 212
28 Large Fairy 10:00 AM Circles 8
29 Large Fairy 10:00 AM Pacing 22
30 Large Fairy 2:00 PM Pacing 7
31 Barren Fairy 7:00 AM Pacing 6
32 Barren Fairy 10:00 AM Pacing 396
33 Barren Fairy 2:00 PM Pacing 132
34 Barren Fairy 6:00 PM Pacing 111
35 Small Ghost 7:00 AM Pacing 3
36 Small Kraken 7:00 AM Pacing 6
37 Small Kraken 7:00 AM Pacing with a hover 790
38 Small Kraken 10:00 AM Pacing with a hover 1204
39 Small Kraken 10:00 AM Zig zag 77
40 Small Kraken 2:00 PM Pacing with a hover 746
41 Small Kraken 2:00 PM Zig zag 64
42 Medium Kraken 10:00 AM Circles 13
43 Medium Kraken 2:00 PM Circles 22
44 Large Kraken 7:00 AM Circles 9
45 Large Kraken 10:00 AM Pacing 77
46 Large Kraken 2:00 PM Circles 43
47 Large Kraken 2:00 PM Pacing 41
48 Large Kraken 6:00 PM Circles 6
49 Barren Kraken 7:00 AM Circles 15
50 Barren Kraken 7:00 AM Zig zag 11
51 Barren Kraken 10:00 AM Circles 41
52 Barren Kraken 10:00 AM Pacing 28
53 Barren Kraken 2:00 PM Pacing 21
54 Barren Kraken 2:00 PM Zig zag 12
55 Barren Kraken 6:00 PM Circles 7
56 Barren Kraken 6:00 PM Pacing 0
57 Small Orange Pendek 10:00 AM Pacing 5
58 Medium Orange Pendek 7:00 AM Pacing 8
59 Medium Orange Pendek 10:00 AM Pacing 41
60 Medium Orange Pendek 2:00 PM Pacing 4
61 Medium Orange Pendek 6:00 PM Pacing 3
62 Large Orange Pendek 7:00 AM Circles 15
63 Jar Phoenix 10:00 AM Pacing 3
64 Small Phoenix 7:00 AM Pacing 7
65 Small Phoenix 2:00 PM Pacing 14
66 Small Phoenix 6:00 PM Pacing 8
67 Medium Phoenix 7:00 AM Pacing 36
68 Medium Phoenix 10:00 AM Pacing 19
69 Medium Phoenix 2:00 PM Pacing 100
70 Medium Phoenix 6:00 PM Pacing 58
71 Large Phoenix 7:00 AM Pacing 6
72 Large Phoenix 10:00 AM Pacing 19
73 Large Phoenix 2:00 PM Pacing 13
74 Large Phoenix 6:00 PM Pacing 8
75 Barren Phoenix 10:00 AM Circles 27
76 Barren Phoenix 10:00 AM Pacing 18
77 Barren Phoenix 2:00 PM Pace then hover 0
78 Barren Phoenix 6:00 PM Circles 3
79 Barren Phoenix 6:00 PM Pace then hover 0
80 Jar Wizard 2:00 PM Pacing 7
81 Small Wizard 7:00 AM Pacing 681
82 Small Wizard 10:00 AM Pacing 8
83 Small Wizard 6:00 PM Pacing 52
84 Medium Wizard 7:00 AM Pacing 35
85 Medium Wizard 10:00 AM Pacing 16
86 Large Wizard 7:00 AM Pacing 35
87 Large Wizard 10:00 AM Pacing 409
88 Large Wizard 2:00 PM Pacing 277
89 Large Wizard 6:00 PM Pacing 185
90 Barren Wizard 7:00 AM Pacing 527
91 Barren Wizard 10:00 AM Pacing 472
92 Barren Wizard 2:00 PM Pacing 432
93 Barren Wizard 6:00 PM Pacing 641
I don’t think there are enough data to really say something about the number of repetitions. The number of repetitions seems pretty unique to a fish in a certain tank. I don’t see ab obvious pattern depending on the tank. The interesting thing is that the stereotypic swimming seemed consistent in a tank for a fish (most or all trials of that day with stereotypic swimming). It is a pitty we couldn’t calculate the repeatability of the binomial glm of Stereotypic Swimming because it would have been interesting.
Tank. Fish were more likely to interact with the surface during a trial in Jar/Medium compared to Large (not significant for Small). Fish in Jar were 4 times [CI 1, 18] more likely to interact with the surface during a trial than fish in Large, and Fish in Medium were 6 times [CI 2, 23] then fish in Large. In addition, fish were 3 times [CI 1, 12] more likely to interact with a surface during a trial in Barren than in Large.
mInteracting0 <-glm(Interacting.bin ~ Tank + Time + Filter, data = data, family =binomial)lrtest(mInteracting0, mInteracting)
Warning in modelUpdate(objects[[i - 1]], objects[[i]]): original model was of
class "glm", updated model is of class "glmmTMB"
Likelihood ratio test
Model 1: Interacting.bin ~ Tank + Time + Filter
Model 2: Interacting.bin ~ Tank + Time + Filter + (1 | Fish)
#Df LogLik Df Chisq Pr(>Chisq)
1 9 -164.2
2 10 -154.7 1 19.008 1.302e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Likelihood ratio test indicates a statistically significant random effect. Meaning that fish behaved differently among each others in terms of interaction with surface.
Just a plot with the type of interaction depending on the tank. To stick with the analysis, it is a count (count = 1 if the fish performs a certain type of interaction with surface during a trial).
Filter prob SE df asymp.LCL asymp.UCL
No-filter 0.2081 0.0621 Inf 0.11154 0.3549
Filter 0.0234 0.0170 Inf 0.00552 0.0935
Results are averaged over the levels of: Tank, Time
Confidence level used: 0.95
Intervals are back-transformed from the logit scale
Effect of Tank and Filter. + Tank. Despite a significant effect of Tank, no contrasts were statistically significant. This is usual when you have a weakly significant fixed effect of a factor (0.01 < p-value < 0.05) which has a lot of different levels. In terms of trend, fish in Jar seemed less likely to build a nest compared to Small/Medium/Large. In addition, fish in Barren were less likely to build nest than fish in Large. + Filter. Fish were more likely to build a nest without a filter in their tank.
mNest0 <-glm(Nest.bin ~ Tank + Time + Filter, data = data, family =binomial)lrtest(mNest0, mNest)
Warning in modelUpdate(objects[[i - 1]], objects[[i]]): original model was of
class "glm", updated model is of class "glmmTMB"
Likelihood ratio test
Model 1: Nest.bin ~ Tank + Time + Filter
Model 2: Nest.bin ~ Tank + Time + Filter + (1 | Fish)
#Df LogLik Df Chisq Pr(>Chisq)
1 9 -110.12
2 10 -104.34 1 11.552 0.0006769 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Likelihood ratio test indicates a statistically significant random effect. Meaning that fish behaved differently among each others in terms of nest building.
It seems that the tank has an influence on whether fish prefer being on the upper half or lower half of the tank.
We can do different models: + Look at the percentage of time spent up of the trial. Fit a beta distribution. Problem: All percentages need to be 0 < perc < 100%. There are trials with 100% so we can’t use beta distribution.
Look at the count of seconds (how many seconds the fish spend up of the tank). Fit a binomial distribution. Problem: The diagnostics plots were very bad when fitting mUp <- glmmTMB(cbind(up, down) ~ Tank + Time + Filter + (1|Fish), data = dataUpDown, family = binomial)
Look simply at the actual time spent up. Fit a normal distribution. The response variable can be adjusted by the fact that the trial were not perfectly 600 sec. \(adj.up= \frac{\text{time spent up} * 600}{\text{trial total duration}}\). It is what has been done.
mUp <-lmer(adj.up ~ Tank + Time + Filter + (1|Fish), data = dataUpDown)anova(mUp, ddf ="Kenward-Roger", type =2)
Type II Analysis of Variance Table with Kenward-Roger's method
Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
Tank 259014 64753 4 237.13 3.9094 0.0042910 **
Time 284189 94730 3 231.06 5.7200 0.0008588 ***
Filter 74698 74698 1 135.88 4.5105 0.0354999 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
emmeans(mUp, ~ Time) # estimated means of time spent swimming depending on the time of the day
Time emmean SE df lower.CL upper.CL
7:00 AM 275 23.9 31.5 227 324
10:00 AM 281 23.9 31.5 232 329
2:00 PM 225 23.9 31.5 177 274
6:00 PM 201 23.9 31.5 152 250
Results are averaged over the levels of: Tank, Filter
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
emmeans(mUp, ~ Filter) # estimated means of time spent swimming depending on the time of the day
Filter emmean SE df lower.CL upper.CL
No-filter 278 20.2 15.4 235 321
Filter 214 28.2 35.1 156 271
Results are averaged over the levels of: Tank, Time
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Effect of Tank, Time and Filter.
Tank. The only statistically significant difference is in between Small and Medium: Fish in Small tank spent on average 103 more seconds [25, 181 95% CI] on the upper half of the tank compared to fish in Medium tanks.
Time. Fish spent more time on the upper half of the tank in the morning.
Filter. Fish spent more time on the upper half of the tank with a filter in their tank.
Plot each fish time with individual data? plotRP1 plotRP2
Conclusion
First, the PCA to show the correlations between variables and to highlight the important variables that contribute to the most of variability in behaviour.
Second, I would do a first big table for the results of the anova with the F-value, NumDf, DenDf and associated p-value for the fixed effects Tank, Filter and Time fixed effects. For the generalised mixed models (foraging, stereotypic swimming, etc), it is not the F-value but the Chisq, Df and p-value Foraging, Stereotypic Swimming, etc). For the linear models, I will also include in this big table the results for the random effect (Variance explained by fish, Residual variance and Repeatability). Then, I would put another table with the results of the contrasts between tanks with the contrast estimates, their confidence intervals, the associated t- or z-tests and p-values for readers to have an idea of the size of the difference between treatments. It is worth noting that the confidence intervals are large which is normal considering the number of fish.
Based on the two tables, what we can say first is that there is a effect of the Tank on all behaviours, the tank is there having a big influence on the betta’s behaviour. Then, it seems that we have three groups for the Jar/Small/Medium/Large
Jar with less likely to build a nest and less likely to perform stereotypic swimming compared to the others
Small and Medium
Large with more time swimming, less time resting, more likely to forage and less likely to interact with the surface
And Large and Barren are two different groups + Barren with less likely to build a nest + Large with more time swimming, more likely to forage and less likely to interact with the surface
Also, I would put something about the fact that each fish behave pretty uniquely.